'use strict';

/**
 * 门禁逻辑控制器
 */
const util = require('util');
const Code = require('../common/error_code');
const Cons = require('../common/constants');
const Config = require('../controllers/config');
const configModel = require('../models/config.model');
const userModel = require('../models/user.model');
const guardModel = require('../models/guard.model');
const pushClient = require('../utils/redis_subscribe');
const guardClient = require('../utils/guard_client');
const Util = require('../utils/hobot_util');
const moment = require("moment");
const logger = require('../utils/logger');

let push_config = {};
/**
 * 订阅推送
 */
push_config.ready_callback = async function () {
    try {
        const guard = await guardModel.find();

        for (let i = 0; i < guard.length; i++) {
            const item = guard[i];
            pushClient.subscribe(item.g_ch);
        }
    } catch (err) {
        logger.logError("\n" + '===== Redis subscribe error - ' + err + ' =====' + "\n");
    }
};
/**
 * 推送回调
 * @param channel
 * @param message
 * @returns {Promise.<void>}
 */
push_config.msg_callback = async function (channel, message) {
    try {
        // console.log("message receive: " + message);
        const jMsg = message;
        const ipcId = jMsg.d_id;
        const userId = jMsg.face_info._id;
        logger.logInfo("\n" + '===== Redis received - ipc: ' + ipcId + ', user: ' + userId + ' =====' + "\n");
        if (ipcId && userId && message.liveness != Cons.RECORD_LIVENESS_NOT_LIVE) {
            const guard = await guardModel.findOne({ _id: ipcId });
            if (!guard || !guard.g_sw) {
                return;
            }

            const permit = await query_permit(ipcId, userId);
            logger.logInfo("\n" + '===== Guard permission - ipc: ' + ipcId
                + ', user: ' + userId + ', permission: ' + permit + ' =====' + "\n");
            if (permit == Cons.USER_ACCESS_PERMIT_NO) {
                return;
            }

            const options = guard.g_sw.split('-');
            if (options.length > 0) {
                const ip = options[0];
                guardClient.openDoor(guard.g_st, ip, options[1], options[2]);
            }
        }
    } catch (err) {
        logger.logError("\n" + '===== Redis received error - ' + err + ' =====' + "\n");
    }
};

/**
 * 查询是否需要开启门禁
 * @param ipcId
 * @param userId
 */
async function query_permit(ipcId, userId) {
    try {
        // 【1】匹配门禁时间设置
        // 【2】匹配门禁权限设置
        // 【3】查询有没有此用户，并且是不是在有效期内
        const now = moment().format('HHmm');
        const week = moment().format('d');
        const permit = await guardModel.findOne({
            _id: ipcId, $and: [{ p_fr: { $lte: now } }, { p_to: { $gte: now } }],
            'u_in.u_id': userId, p_wk: { $elemMatch: { 'week': week, 'value': 1 } }
        });
        if (!permit) {
            return Cons.USER_ACCESS_PERMIT_NO;
        }
        // 下面的做法有点low，先废弃掉
        // if (now < permit.p_fr || now > permit.p_to) {
        //     return Cons.USER_ACCESS_PERMIT_NO;
        // }
        // if (permit.p_wk) {
        //     for (let w of permit.p_wk) {
        //         if (w.week == week) {
        //             if (w.value && w.value == 1) {
        //                 break;
        //             } else {
        //                 return Cons.USER_ACCESS_PERMIT_NO;
        //             }
        //         }
        //     }
        // } else {
        //     return Cons.USER_ACCESS_PERMIT_NO;
        // }

        const user = await userModel.findOne({ _id: userId });
        if (!user) {
            return Cons.USER_ACCESS_PERMIT_NO;
        }
        // 非正式员工都要校验有效期限
        if (user.u_tp != Cons.USER_TYPE_STAFF) {
            if (!user.p_fr || !user.p_to) {
                return Cons.USER_ACCESS_PERMIT_NO;
            }
            const start = Util.fmtDate(user.p_fr, 'YYYYMMDD');
            const end = Util.fmtDate(user.p_to, 'YYYYMMDD');
            const today = moment().format('YYYYMMDD');
            if (today < start || today > end) {
                return Cons.USER_ACCESS_PERMIT_NO;
            }
        }

        return Cons.USER_ACCESS_PERMIT_OK;
    } catch (err) {
        return Cons.USER_ACCESS_PERMIT_NO;
    }
}

/**
 * 查询门禁
 */
async function query(ctx) {
    const lookup = {
        from: "ipc",
        localField: "_id",
        foreignField: "_id",
        as: "ipc_docs"
    };
    const project1 = { _id: 1, p_fr: 1, p_to: 1, p_wk: 1, g_ch: 1, u_in: 1, ipc: { $arrayElemAt: ['$ipc_docs', 0] } };
    const project2 = { _id: 1, d_nm: '$ipc.d_nm', p_fr: 1, p_to: 1, p_wk: 1, g_ch: 1, u_in: 1 };
    const guard = await guardModel.aggregate([{ $lookup: lookup }, { $project: project1 }, { $project: project2 }]);

    let rst = [];
    for (let i = 0; i < guard.length; i++) {
        const item = guard[i];
        let pFrom = Cons.GUARG_TIME_FROM;
        let pTo = Cons.GUARG_TIME_TO;
        let pWeek = { "0": 0, "1": 1, "2": 1, "3": 1, "4": 1, "5": 1, "6": 0 };
        let arrPermit = [];
        const permit = await guardModel.findOne({ _id: item._id });
        if (permit) {
            // 时间
            if (permit.p_fr) {
                pFrom = permit.p_fr;
            }
            if (permit.p_to) {
                pTo = permit.p_to;
            }
            if (permit.p_wk) {
                pWeek = {};
                permit.p_wk.forEach(function (item, index) {
                    pWeek[item.week] = item.value;
                });
            }
            // 权限
            if (permit.u_in) {
                permit.u_in.forEach(function (item, index) {
                    arrPermit.push(item.u_id);
                });
            }
        }

        // 门禁开放时间
        let guardWeek = '';
        for (let i = 0; i <= 6; i++) {
            if (pWeek[i] == 1) {
                if (guardWeek) {
                    guardWeek += ', ';
                }
                if (i == 0) {
                    guardWeek += '周日';
                } else if (i == 1) {
                    guardWeek += '周一';
                } else if (i == 2) {
                    guardWeek += '周二';
                } else if (i == 3) {
                    guardWeek += '周三';
                } else if (i == 4) {
                    guardWeek += '周四';
                } else if (i == 5) {
                    guardWeek += '周五';
                } else if (i == 6) {
                    guardWeek += '周六';
                }
            }
        }

        rst.push({
            ipc_id: item._id,
            ipc_name: item.d_nm,
            guard_time: util.format('%s - %s', convertTime(pFrom), convertTime(pTo)),
            guard_week: guardWeek,
            permit_from: pFrom,
            permit_to: pTo,
            permit_week: pWeek,
            ipc_permit: arrPermit
        });
    }
    ctx.success(Code.RET_GUARD_LIST_QUERY_OK, rst);
}

/**
 * 查询全员信息供门禁权限设置
 */
async function query_users(ctx) {
    const opt = {
        u_hp: 0
    };
    const users = await userModel.find('', opt).sort({ 'u_tp': 1, 'u_dm': 1 });

    const depts = await Config.getDeptList();
    let rst = [];
    for (let i = 0; i < users.length; i++) {
        const item = users[i];
        let dept = '';
        if (item.u_tp == Cons.USER_TYPE_GUEST) {
            dept = '临时访客';
        } else if (item.u_tp == Cons.USER_TYPE_VIP) {
            dept = 'VIP客户';
        } else {
            dept = Config.getConfigLabel(depts, item.u_dm);
        }
        rst.push({
            key: item._id,
            user_name: item.u_nm,
            user_dept: dept
        });
    }
    ctx.success(Code.RET_GUARD_USERS_QUERY_OK, rst);
}

/**
 * 门禁时间设置
 */
async function setting(ctx) {
    const params = ctx.request.body;
    // 校验参数
    if (!params.ipc_id || !params.time_from || !params.time_to || !params.week_info) {
        return ctx.error(Code.RET_GUARD_SET_TIME_ERR_PARAM);
    }
    if (!Util.isDate(params.time_from, 'HHmm') || !Util.isDate(params.time_to, 'HHmm')) {
        return ctx.error(Code.RET_GUARD_SET_TIME_ERR_PARAM);
    }

    // guard存在性校验
    const cdt = { _id: params.ipc_id };
    const guard = await guardModel.findOne(cdt);
    if (!guard) {
        return ctx.error(Code.RET_GUARD_SET_ERR_NOT_EXIST);
    }

    let arr = [];
    // 周日
    arr.push({ week: "0", value: params.week_info[0] });
    // 周一
    arr.push({ week: "1", value: params.week_info[1] });
    // 周二
    arr.push({ week: "2", value: params.week_info[2] });
    // 周三
    arr.push({ week: "3", value: params.week_info[3] });
    // 周四
    arr.push({ week: "4", value: params.week_info[4] });
    // 周五
    arr.push({ week: "5", value: params.week_info[5] });
    // 周六
    arr.push({ week: "6", value: params.week_info[6] });

    const pModel = {
        p_fr: params.time_from,
        p_to: params.time_to,
        p_wk: arr
    };
    await guardModel.update(cdt, pModel, { upsert: true });
    ctx.success(Code.RET_GUARD_SET_TIME_OK);
}

/**
 * 门禁权限设置
 */
async function permit(ctx) {
    const params = ctx.request.body;
    // 校验参数
    if (!params.ipc_id || !params.in_users || params.in_users.length === 0) {
        return ctx.error(Code.RET_GUARD_SET_PERMIT_ERR_PARAM);
    }

    // guard存在性校验
    const cdt = { _id: params.ipc_id };
    const guard = await guardModel.findOne(cdt);
    if (!guard) {
        return ctx.error(Code.RET_GUARD_SET_ERR_NOT_EXIST);
    }

    let arr = [];
    for (let item of params.in_users) {
        const user = await userModel.findOne({ _id: item });
        if (user) {
            arr.push({ u_id: item });
        }
    }
    const pModel = { u_in: arr };
    await guardModel.update(cdt, pModel, { upsert: true });
    ctx.success(Code.RET_GUARD_SET_PERMIT_OK);
}

/**
 * 查询门禁设置（APP专供）
 */
async function query_guard_time(ctx) {
    const params = ctx.request.query;
    // 校验参数
    if (!params.ipc_id) {
        return ctx.error(Code.RET_APP_QUERY_PERMIT_ERR_PARAM);
    }

    const permit = await guardModel.findOne({ _id: params.ipc_id }, { u_in: 0 });
    let rst = '';
    if (permit) {
        rst = {
            ipc_id: permit._id,
            permit_from: convertTime(permit.p_fr),
            permit_to: convertTime(permit.p_to),
            permit_week: permit.p_wk
        };
        ctx.success(Code.RET_APP_QUERY_PERMIT_OK, rst);
    } else {
        ctx.error(Code.RET_APP_QUERY_PERMIT_ERR_NOT_EXIST);
    }
}

/**
 * 0800 >>> 08:00
 */
function convertTime(input) {
    let out = input;
    if (input && input.length >= 4) {
        out = input.substr(0, 2) + ':' + input.substr(2, 2);
    }
    return out;
}


// 订阅推送
exports.push_config = push_config;
// 查询门禁
exports.query = query;
// 查询全员信息供门禁权限设置
exports.query_users = query_users;
// 门禁时间设置
exports.setting = setting;
// 门禁权限设置
exports.permit = permit;

// 查询门禁设置（APP专供）
exports.query_guard_time = query_guard_time;

